package be.bejug.setris.swinggui

import java.awt.event.{KeyEvent, KeyAdapter}
import be.bejug.setris.{SetrisGame, TileGrid, SetrisGui}
import be.bejug.setris.swingtools.SwingTools._
import javax.swing.{ImageIcon, BorderFactory, BoxLayout, Timer, JLabel, JPanel, JButton, JFrame}
import java.awt.{Toolkit, Image, Font, Color, BorderLayout}

/**
 * Implementation of a  { @link SetrisGui } using Java Swing
 */
class SetrisFrame extends JFrame("SETRIS") with SetrisGui {
  val playFieldDimension: (Int, Int) = (10, 20)
  val frameRate: Int = 50

  //Default font for the labels
  private val labelFont = new Font(Font.SANS_SERIF, Font.BOLD, 24)


  private val playField = new TileGridView(new TileGrid(playFieldDimension._1, playFieldDimension._2))
  private val nextBlockField = new TileGridView(new TileGrid(4, 4))
  private val scoreLabel = newLabel("0", true)
  private val levelLabel = newLabel("0", true)
  private val btnStart = new JButton("Start game")
  private val gameOverLabel = newLabel("GAME OVER", true)
  private var timer = new Timer(1000 / frameRate, doTick)
  private var game: Option[SetrisGame] = None
  private val bgColor = Color.BLACK
  private val fgColor = Color.WHITE                                   

  buildScreen
  setIconImage(Toolkit.getDefaultToolkit.getImage(this.getClass.getResource("/Scala.png")))
  setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE)
  getContentPane.setFocusable(true)
  pack()
  getContentPane.addKeyListener(
    new KeyAdapter {
      override def keyPressed(e: KeyEvent): Unit = {
        e.getKeyCode match {
          case KeyEvent.VK_LEFT => game.foreach(_.moveLeft)
          case KeyEvent.VK_RIGHT => game.foreach(_.moveRight)
          case KeyEvent.VK_SPACE => game.foreach(_.dropBlock)
          case KeyEvent.VK_DOWN => game.foreach(_.dropBlock)
          case KeyEvent.VK_UP => game.foreach(_.rotateRight)
          case other => ()
        }
      }

      override def keyReleased(e: KeyEvent): Unit = {
        e.getKeyCode match {
          case KeyEvent.VK_DOWN => game.foreach(_.dropBlock)
          case other => ()
        }
      }
    }
    )
  setVisible(true)
  getContentPane.requestFocus




  def setGame(game: SetrisGame) {
    this.game = Some(game)
  }

  private def buildScreen {
    val c = getContentPane
    c.setBackground(bgColor)
    c.setForeground(fgColor)
    c.setLayout(new BorderLayout(12, 12))
    c.add(playField, BorderLayout.CENTER)
    c.add(buildStatusPanel, BorderLayout.WEST)
    c.add(gameOverLabel, BorderLayout.SOUTH)
    c.add(nextBlockField, BorderLayout.EAST)

    playField.setBorder(BorderFactory.createLineBorder(Color.WHITE, 12))
    playField.setForeground(Color.WHITE)
    nextBlockField.setForeground(bgColor) //Don't show the grid

    setGameOver(true)
  }

  private def buildStatusPanel = {
    val result = new JPanel()
    result.setForeground(getContentPane.getForeground)
    result.setBackground(getContentPane.getBackground)
    result.setLayout(new BoxLayout(result, BoxLayout.Y_AXIS))
    result.add(newLabel("Level"))
    result.add(levelLabel)
    result.add(newLabel("Score"))
    result.add(scoreLabel)
    result.add(btnStart)
    btnStart.addActionListener(btnStartClicked)
    btnStart.setFocusable(false)
    result
  }


  private def newLabel(text: String, bright: Boolean = false): JLabel = {
    val result = new JLabel(text)
    result.setFont(labelFont)
    result.setForeground(if (bright) Color.WHITE else Color.LIGHT_GRAY)
    result
  }


  private var tickCount = 0

  private def doTick {
    tickCount += 1
    game.foreach(_.tick(tickCount))
  }

  private def btnStartClicked {
    game.foreach {
      g =>
        g.start
        timer.start
    }
    btnStart.setEnabled(false)
  }

  def setGameOver(over: Boolean): Unit = {
    if (over) {
      gameOverLabel.setText("GAME OVER !!!")
      timer.stop
    } else {
      gameOverLabel.setText(" ")
    }

    btnStart.setEnabled(over)
  }

  def setScore(aScore: Int) = scoreLabel.setText(aScore.toString)

  def setPlayField(aPlayField: TileGrid) = playField.data = aPlayField

  def setLevel(aLevel: Int) = levelLabel.setText(aLevel.toString)

  def setNextBlock(block: TileGrid) = nextBlockField.data = nextBlockField.data.clear.draw(0, 0, block)

}







